import * as ol from '../openLayer'
import { getVectorContext } from 'ol/render.js'
import { getDistance } from 'ol/sphere.js'
import { PlaybarControl } from './play'
import { defaultConfig } from './config'
import { deepAssign } from '@/utils/tools/deepAssign'
import { LineString } from 'ol/geom'
/**
 * 轨迹类
 */
export default class OlMapTrajectory {
  constructor (_map, _config) {
    this.map = _map
    this.options = deepAssign(defaultConfig, _config) //  配置项
    this.line = null // 直线
    this.lineFeature = null // 直线feature
    this.startMarker = null // 开始点位
    this.endMarker = null // 结束点位
    this.stopMakers = [] // 经停点
    this.routeStyle = null // 轨迹样式
    this.movePoint = null // 移动点
    this.movePointMarker = null //  移动点feature
    this.moveFeature = null // 移动feature
    this.lastTime = null //  最后一次移动时间
    this.animating = false // 是否正在移动，false-> 停止 true-> 移动
    this.trajectoryLayer = null //  openlayer 对象
    this.speed = this.options.speed //  移动速度
    this.distance = 0 // 已经移动的距离
    this.currentIndex = 0 //  当前坐标点下标
    this.lineAllLength = 0 //  轨迹总长度
    this.lineSegmentLength = [] // 线段直接的距离
    this.vectorContext = null // canvas 上下文
    this.tolerance = this.options.tolerance < 10 ? 10 : this.options.tolerance // 容差，最小为10
    this.imageAngle = this.options.imageAngle //  图片自身旋转角度
    if (this.options.coordinates.length > 0) {
      this.setRouteStyle() //  设置轨迹样式
      this.drwaRoute() //  绘制线条
      this.initMoveFeature() //  初始化移动moveFeature
      // this.lineAllLength = this.getLineAllLength() //  获取线条总长度
      this.playbarControl = new PlaybarControl(this.map, _config, (e, pos) => { //  添加播放停止动画控制器
        if (pos === 100) { // 在尾端
          this.movePoint.setCoordinates(this.options.coordinates[0]) // 设置移动点当前位置
          this.movePointMarker.setGeometry(this.movePoint)
          this.distance = 0
          this.currentIndex = 0
          // this.redrawMovePoing(this.options.coordinates[0], this.options.coordinates) // 设置移动点到一个点位
        }
        this.setAnimation(e)
      }, (e) => {
        this.setAnimationSpeed(e)
      })
      this.map.addControl(this.playbarControl)
    }
  }

  /**
   * 重新绘制移动点位置和样式
   */
  redrawMovePoing (currentCoordinate, coordinates, vectorContext) {
    this.movePoint.setCoordinates(currentCoordinate) // 设置移动点当前位置
    // console.log('this.currentIndex=', this.currentIndex, this.getRotation(coordinates[this.currentIndex], coordinates[this.currentIndex + 1]))
    let rotation = this.getRotation(coordinates[this.currentIndex], coordinates[this.currentIndex + 1])
    if (rotation > 3) {
      rotation = rotation - this.imageAngle
    }
    let movePointStyle = new ol.Style({
      image: new ol.Icon({
        src: this.options.navStyle.url,
        scale: this.options.navStyle.scale,
        rotateWithView: false,
        rotation: rotation

      })
    })
    this.vectorContext.setStyle(movePointStyle) //  移动时重新计算线路角度
    this.vectorContext.drawGeometry(this.movePoint)
  }

  /**
 * 得到总线路长度
 * @returns
 */
  getLineAllLength () {
    let coordinates = this.options.coordinates
    let length = 0
    for (let i = 0; i < coordinates.length - 1; i++) {
      // console.log(coordinates[i], i)
      length = length + this.formatLength(coordinates[i], coordinates[i + 1])
      this.lineSegmentLength.push(parseInt(length))
    }
    console.log('this.lineSegmentLength', this.lineSegmentLength)
    return length
  }

  /**
   * 设置动画的速度
   * @param {*} e
   */
  setAnimationSpeed (e) {
    this.speed = e * this.options.speed
    // this.initMoveFeature()
  }

  /**
   * 开启或者停止动画
   * @param {*} e
   */
  setAnimation (e) {
    // console.log('e', e)
    this.animating = e
    if (this.animating) {
      this.startAnimation()
    } else {
      this.stopAnimation()
    }
  }
  /**
   * 开始动画
   */

  startAnimation () {
    console.log('开始移动')
    this.animating = true
    this.lastTime = new Date().getTime() /** 开始时的时间 */
    this.trajectoryLayer.on('postrender', this.moveFeature)
    // hide geoMarker and trigger map render through change event
    this.movePointMarker.setGeometry(null)
  }

  /**
 * 停止动画
 */
  stopAnimation () {
    this.animating = false

    // Keep marker at current animation position
    this.movePointMarker.setGeometry(this.movePoint)
    this.trajectoryLayer.un('postrender', this.moveFeature)
  }

  /**
 * 获取线段长度
 * @param {*} line
 * @returns
 */
  formatLength (sourcePoint, targetPoint) {
    const length = getDistance(sourcePoint, targetPoint)
    let output
    if (length > 1000) {
      output = Math.round((length / 1000) * 100) / 100 + ' km'
    } else {
      output = Math.round(length * 100) / 100 + ' m'
    }
    return getDistance(sourcePoint, targetPoint)
  };
  /**
  * 根据坐标获取角度数，以正上方为0度作为参照
  * @param  sourcePoint 源点
  * @param  targetPoint 目标点
  */

  getRotation (sourcePoint, targetPoint) {
    try {
      return -Math.atan2(targetPoint[1] - sourcePoint[1], targetPoint[0] - sourcePoint[0]) + this.imageAngle //  计算导航图标旋转角度
    } catch (error) {
      console.log(error, sourcePoint, targetPoint)
    }
  }

  /**
   * 初始化移动
   */
  initMoveFeature () {
    if (this.moveFeature) {
      console.log('已存在', this.moveFeature)
    } else {
      let routeLength = this.options.coordinates.length
      let coordinates = this.options.coordinates
      let moveLength = 0
      let preCoordinate = this.options.coordinates[0]

      this.moveFeature = (e) => {
        // console.log('moveFeaturee=', e)
        this.vectorContext = getVectorContext(e) // //HTML5 Canvas context，ol.render.canvas.Immediate的对象
        const speed = parseInt(this.speed)
        let frameState = e.frameState // freme 的状态
        const time = frameState.time
        const elapsedTime = time - this.lastTime
        if (this.distance === 0) {
          preCoordinate = this.options.coordinates[0]
          moveLength = 0
          this.lastTime = new Date().getTime()
        }
        // console.log('frameStateindex=', frameState.index)
        this.distance = (this.distance + (speed * elapsedTime) / 1e6) % 2

        // console.log('this.currentIndex=', this.currentIndex)
        // console.log('distance', distance)
        this.lastTime = time
        const currentCoordinate = this.line.getCoordinateAt(
          this.distance > 1 ? 2 - this.distance : this.distance
        )
        moveLength = moveLength + this.formatLength(preCoordinate, currentCoordinate) // 计算移动过的距离
        preCoordinate = currentCoordinate //  缓存上一个定位点
        // console.log('moveLength=', currentCoordinate, moveLength)
        // console.log('moveLength=', moveLength, this.lineSegmentLength.indexOf(moveLength))

        let progressWidth = (moveLength / this.lineAllLength) * 100 //  计算计算进度条的位置
        // console.log('progressWidth=', progressWidth)
        this.playbarControl.setProgressEleWidth(progressWidth) //  设置进度条的位置
        this.getCurrentIndex(moveLength, coordinates) // 计算移动点在坐标数组里的下标
        this.redrawMovePoing(currentCoordinate, coordinates) // 从新绘制移动点的位置
        this.map.render() // 继续动画效果
        if (this.distance > 1) {
          this.stopAnimation()
        }
      }
    }
  }

  /**
   * 计算当前坐标点下标,
   * moveLength
   */
  getCurrentIndex (moveLength, coordinates) {
    let filtCoordinate = this.lineSegmentLength.filter(item => {
      let tempMoveLength = parseInt(moveLength)
      let tempItem
      // console.log(tempMoveLength, item)
      if (tempMoveLength > item - this.tolerance && tempMoveLength < item + this.tolerance) {
        tempItem = item
      }
      return tempItem
    })
    // console.log('filtCoordinate=', filtCoordinate)
    if (filtCoordinate.length > 0) {
      this.currentIndex = this.lineSegmentLength.indexOf(filtCoordinate[0])
      // console.log('this.currentIndex=', this.currentIndex)
    }
    if (this.currentIndex >= coordinates.length) {
      this.currentIndex = coordinates.length - 1
    }
  }

  /**
   * 道路轨迹
   */
  drwaRoute () {
    this.line = new LineString(this.options.coordinates) //  直线
    // 线路所有坐标点坐标
    let coordinates = this.options.coordinates
    this.lineFeature = new ol.Feature({ //  直线线路
      type: 'line',
      geometry: this.line
    })
    this.startMarker = new ol.Feature({ //  开始点位
      type: 'icon',
      geometry: new ol.Point(this.line.getFirstCoordinate())
    })
    this.endMarker = new ol.Feature({ //  结束点位
      type: 'icon',
      geometry: new ol.Point(this.line.getLastCoordinate())
    })
    /**
     * 经停点
     */

    for (let i = 0; i < coordinates.length; i++) {
      let s = new ol.Feature({
        type: 'stop',
        geometry: new ol.Point(coordinates[i].point)
      })
      this.stopMakers.push(s)
    }

    this.movePoint = this.startMarker.getGeometry().clone() // 移动点
    this.movePointMarker = new ol.Feature({ //  移动点feature
      type: 'geoMarker',
      geometry: this.movePoint
    })

    let routeFeature = [...[this.lineFeature, this.movePointMarker, this.startMarker, this.endMarker], ...this.stopMakers]

    this.trajectoryLayer = new ol.VectorLayer({ // 添加图层
      source: new ol.VectorSource({
        features: routeFeature,
        className: 'TrajectoryLayer',
        properties: this.options.layerProperties
      }),
      style: (feature) => {
        return this.routeStyle[feature.get('type')]
      }

    })

    this.map.addLayer(this.trajectoryLayer)
  }

  /**
   * 设置轨迹线路样式
   */
  setRouteStyle () {
    let coordinates = this.options.coordinates
    let sourcePoint = coordinates[this.currentIndex]
    let targetPoint = coordinates[this.currentIndex + 1]

    this.routeStyle = { // 定义线路样式
      line: new ol.Style({
        stroke: new ol.Stroke({
          width: this.options.lineStyle.width,
          color: this.options.lineStyle.color
        })
      }),

      geoMarker: new ol.Style({
        image: new ol.Icon({
          src: this.options.navStyle.url,
          scale: this.options.navStyle.scale,
          rotateWithView: false,
          rotation: this.getRotation(sourcePoint, targetPoint)

        })

      }),
      stop: new ol.Style({
        image: new ol.CircleStyle({
          radius: this.options.stopStyle.radius - 2,
          fill: new ol.Fill({
            // width: this.options.routeStyle.width,
            color: this.options.stopStyle.color
          }),
          stroke: new ol.Stroke({
            width: (this.options.stopStyle.radius - 2) / 2,
            color: this.options.stopStyle.color
          })
        })
      })
    }
  }

  updateTrajectory (_map, _config) {
    this.map = _map
    this.options = deepAssign(defaultConfig, _config) //  配置项
  }
}
